`timescale 1ns / 1ps

///////////////////////////////////////////////////////////////////////
//
//  Codigo tomado del libro FPGA Prototyping By Verilog Examples
//  Autor: Pong P. Chu
//  Capitulo 13 VGA Controller
//
///////////////////////////////////////////////////////////////////////
module vga_sync(
	input wire clk_i, rst_i,
	output wire hsync_o, vsync_o, video_on_o,
	output wire [9:0] pixel_x_o, pixel_y_o
   );
	 
	// Decalracion de constantes
	// Parametros de sincronizacion de VGA para 640 x 480 pixeles y bordes de pantalla
	localparam HD = 640;
	localparam HF = 48;
	localparam HB = 16;
	localparam HR = 96;
	localparam VD = 480;
	localparam VF = 10;
	localparam VB = 33;
	localparam VR = 2;
	
	// Selector de reduccion de senal de reloj a 25MHz
	reg mod2_reg;
	wire mod2_next;
	
	// Contadores de senales de sincronizacion
	reg [9:0] h_count_reg, h_count_next;
	reg [9:0] v_count_reg, v_count_next;
	
	reg v_sync_reg, h_sync_reg;
	wire v_sync_next, h_sync_next;
	
	// Senal de estatus
	wire h_end, v_end; //pixel_tick;

	// Buffer de salida
	always @(posedge clk_i, posedge rst_i)
		if (rst_i)
			begin
				mod2_reg <= 1'b0;
				v_count_reg <= 0;
				h_count_reg <= 0;
				v_sync_reg <= 1'b0;
				h_sync_reg <= 1'b0;
			end	
		else
			begin
				mod2_reg <= mod2_next;
				v_count_reg <= v_count_next;
				h_count_reg <= h_count_next;
				v_sync_reg <= v_sync_next;
				h_sync_reg <= h_sync_next;
			end
			
	// Generacion de reloj de 25MHz
	assign mod2_next = ~mod2_reg;
	assign pixel_tick = mod2_reg;
	

	// Fin de contador de senal horizontal (799)
	assign h_end = (h_count_reg==(HD+HF+HB+HR-1));
	// Fin de contador de senal vertical (524)
	assign v_end = (v_count_reg==(VD+VF+VB+VR-1));
	
	// Logica de aumento de senal horizontal
	always @*
		if (pixel_tick) //25MHz
			if (h_end)
				h_count_next = 0;
			else
				h_count_next = h_count_reg + 1;
		else
			h_count_next = h_count_reg;
	
	// Logica de aumento de senal vertical
	always @*
		if (pixel_tick & h_end)
			if (v_end)
				v_count_next = 0;
			else 
				v_count_next = v_count_reg + 1;
		else
			v_count_next = v_count_reg;
			
	// Buffer de senales para evitar glitches
	//h_sync_nxt entre 656 y 751
	assign h_sync_next = (h_count_reg>=(HD+HB) && h_count_reg<=(HD+HB+HR-1));
	//v_sync_nxt entre 490 y 491
	assign v_sync_next = (v_count_reg>=(VD+VB) && v_count_reg<=(VD+VB+VR-1));
	
	// Senal de video encendido y apagado
	assign video_on_o = (h_count_reg<HD) && (v_count_reg<VD);
	
	// Salida del modulo
	assign hsync_o = h_sync_reg;
	assign vsync_o = v_sync_reg;
	assign pixel_x_o = h_count_reg;
	assign pixel_y_o = v_count_reg;
	
endmodule
